package moe.server;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.logging.Logger;

import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseFactory;
import org.apache.http.HttpStatus;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.ProtocolException;
import org.apache.http.StatusLine;
import org.apache.http.UnsupportedHttpVersionException;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.HttpRequestHandlerResolver;
import org.apache.http.protocol.HttpService;

public class MoeHttpService extends HttpService {
	private static final Logger log = Logger.getLogger(MoeHttpService.class.getName());

	public MoeHttpService(HttpProcessor processor, ConnectionReuseStrategy connStrategy,
			HttpResponseFactory responseFactory, HttpRequestHandlerResolver handlerResolver,
			HttpParams params) {
		super(processor, connStrategy, responseFactory, handlerResolver, params);
	}

	@Override
	protected void handleException(final HttpException ex, final HttpResponse response) {
		if (ex instanceof MethodNotSupportedException) {
			response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
		} else if (ex instanceof UnsupportedHttpVersionException) {
			response.setStatusCode(HttpStatus.SC_HTTP_VERSION_NOT_SUPPORTED);
		} else if (ex instanceof ProtocolException) {
			response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
		} else {
			response.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
		}

		EntityTemplate entity = new EntityTemplate(new ContentProducer() {
			public void writeTo(OutputStream stream) throws IOException {
				StatusLine status = response.getStatusLine();
				PrintWriter pw = new PrintWriter(stream, true);
				pw.println("HTTP Status " + status.getStatusCode() + " - "
						+ status.getReasonPhrase());
				pw.println("Exception:");
				ex.printStackTrace(new PrintStream(stream));
				Throwable root = ex;
				while (root.getCause() != null) {
					root = root.getCause();
				}
				pw.println("root cause:");
				root.printStackTrace(new PrintStream(stream));
				log.warning("Exception: " + root.getMessage());
				stream.flush();
			}
		});
		entity.setContentType("text/plain; charset=UTF-8");
		response.setEntity(entity);
	}

	@Override
	protected void doService(final HttpRequest request, final HttpResponse response, final HttpContext context)
			throws HttpException, IOException {
		if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
			super.doService(request, response, context);
		}
	}
}
